// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.api.ads.adwords.lib.utils;

import com.google.api.ads.adwords.lib.client.AdWordsSession;
import com.google.api.ads.common.lib.auth.OAuth2AuthorizationHeaderProvider;
import com.google.api.ads.common.lib.auth.OAuthAuthorizationHeaderProvider;
import com.google.api.ads.common.lib.exception.OAuthException;
import com.google.api.client.http.GenericUrl;
import com.google.common.annotations.VisibleForTesting;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Helper class that generates a configured HttpURLConnection for report downloads.
 *
 * @author Kevin Winter
 */
public class ReportUrlConnectionHelper {

  private static final Logger logger = LoggerFactory.getLogger(
      AdHocReportDownloadHelper.class.getPackage().getName() + ".report_download");

  /** The URI of the download server. */
  public static final String DOWNLOAD_SERVER_URI = "/api/adwords/reportdownload";

  /** HTTP Request Method */
  private static final String REQUEST_METHOD = "POST";

  private final OAuthAuthorizationHeaderProvider oAuthAuthorizationHeaderProvider;
  private final OAuth2AuthorizationHeaderProvider oAuth2AuthorizationHeaderProvider;
  private final AdWordsSession session;

  /**
   * Constructor that instantiates OAuthProdivders.
   *
   * @param session to use when making requests.
   */
  ReportUrlConnectionHelper(AdWordsSession session) {
    this.session = session;
    this.oAuthAuthorizationHeaderProvider = new OAuthAuthorizationHeaderProvider(REQUEST_METHOD);
    this.oAuth2AuthorizationHeaderProvider = new OAuth2AuthorizationHeaderProvider();
  }

  /**
   * Gets the report HTTP URL connection given report URL and proper information needed to
   * authenticate the request.
   *
   * @param reportUrl the URL of the report response or download
   * @return the report HTTP URL connection
   * @throws MalformedURLException if the report URL could not be used
   * @throws IOException if there was a problem connecting to the URL
   * @throws ReportException if there were any other problems (such as errors with OAuth).
   */
  @VisibleForTesting
  HttpURLConnection getReportHttpUrlConnection(String reportUrl)
      throws MalformedURLException, IOException, ReportException {
    HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL(reportUrl).openConnection();
    httpUrlConnection.setRequestMethod(REQUEST_METHOD);
    logger.info("{} {}", REQUEST_METHOD, reportUrl);

    if (session.getClientLoginToken() != null) {
      httpUrlConnection.setRequestProperty("Authorization", "GoogleLogin auth="
          + session.getClientLoginToken());
    } else if (session.getOAuthParameters() != null) {
      String authorizationHeader;
      try {
        authorizationHeader = oAuthAuthorizationHeaderProvider.getOAuthAuthorizationHeader(
            session, new GenericUrl(reportUrl));
        httpUrlConnection.setRequestProperty("Authorization", authorizationHeader);
      } catch (OAuthException e) {
        throw new ReportException("Could not set OAuth header", e);
      }
    } else if (session.getOAuth2Credential() != null) {
      String authorizationHeader;
      authorizationHeader = oAuth2AuthorizationHeaderProvider.getOAuth2AuthorizationHeader(session);
      httpUrlConnection.setRequestProperty("Authorization", authorizationHeader);
    } else {
      throw new IllegalArgumentException(
          "Either ClientLoginToken or OAuth header must be provided.");
    }

    httpUrlConnection.setRequestProperty("developerToken", session.getDeveloperToken());
    logger.info("developerToken: {}", session.getDeveloperToken());
    httpUrlConnection.setRequestProperty("clientCustomerId", session.getClientCustomerId());
    logger.info("clientCustomerId: {}", session.getClientCustomerId());
    httpUrlConnection.setRequestProperty("returnMoneyInMicros", Boolean.toString(
        session.isReportMoneyInMicros()));
    logger.info("returnMoneyInMicros: {}", session.isReportMoneyInMicros());

    return httpUrlConnection;
  }
}
